#include <stdio.h>
#include <string.h>

#include "src/msg/ver_to_vernum.h"

namespace re2c_test {

struct examples_t {
    const char* in;
    const char* expected;
};

static constexpr examples_t EXAMPLES[] = {
    { "",            "", },
    { "1",           "010000", },
    { "1.1",         "010100", },
    { "1.1",         "010100", },
    { "1.1.1",       "010101", },
    { "1.1.1.1",     "010101", },
    { "12",          "120000", },
    { "1.12",        "011200", },
    { "12.1",        "120100", },
    { "1.1.12",      "010112", },
    { "1.12.1",      "011201", },
    { "12.1.1",      "120101", },
    { "1.1.1.12",    "010101", },
    { "1.1.12.1",    "010112", },
    { "1.12.1.1",    "011201", },
    { "12.1.1.1",    "120101", },

    // more than 2-digit components not supported
    { "123",         "", },
    { "1.123",       "", },
    { "123.1",       "", },
    { "1.1.123",     "", },
    { "1.123.1",     "", },
    { "123.1.1",     "", },
    { "1.1.1.123",   "", },
    { "1.1.123.1",   "", },
    { "1.123.1.1",   "", },
    { "123.1.1.1",   "", },

    // occasional versions with suffix
    { "dev",         "", },
    { "1.dev",       "010000", },
    { "1.1.dev",     "010100", },
    { "1.1.1.dev",   "010101", },
    { "1.1.1.1.dev", "010101", },

    // old re2c versions
    { "1.1",      "010100" },
    { "1.0.3",    "010003" },
    { "1.0.2",    "010002" },
    { "1.0.1",    "010001" },
    { "1.0",      "010000" },
    { "0.16",     "001600" },
    { "0.15.3",   "001503" },
    { "0.15.2",   "001502" },
    { "0.15.1",   "001501" },
    { "0.15",     "001500" },
    { "0.14.3",   "001403" },
    { "0.14.2",   "001402" },
    { "0.14.1",   "001401" },
    { "0.14",     "001400" },
    { "0.13.7.5", "001307" },
    { "0.13.7.4", "001307" },
    { "0.13.7.3", "001307" },
    { "0.13.7.2", "001307" },
    { "0.13.7.1", "001307" },
    { "0.13.7",   "001307" },
    { "0.13.6",   "001306" },
    { "0.13.5",   "001305" },
    { "0.13.4",   "001304" },
    { "0.13.3",   "001303" },
    { "0.13.2",   "001302" },
    { "0.13.1",   "001301" },
    { "0.13.0",   "001300" },
    { "0.12.3",   "001203" },
    { "0.12.2",   "001202" },
    { "0.12.1",   "001201" },
    { "0.12.0",   "001200" },
    { "0.11.3",   "001103" },
    { "0.11.2",   "001102" },
    { "0.11.1",   "001101" },
    { "0.11.0",   "001100" },
    { "0.10.8",   "001008" },
    { "0.10.7",   "001007" },
    { "0.10.6",   "001006" },
    { "0.10.5",   "001005" },
    { "0.10.4",   "001004" },
    { "0.10.3",   "001003" },
    { "0.10.2",   "001002" },
    { "0.10.1",   "001001" },
    { "0.10.0",   "001000" },
    { "0.9.12",   "000912" },
    { "0.9.11",   "000911" },
    { "0.9.10",   "000910" },
    { "0.9.9",    "000909" },
    { "0.9.8",    "000908" },
    { "0.9.7",    "000907" },
    { "0.9.6",    "000906" },
    { "0.9.5",    "000905" },
    { "0.9.4",    "000904" },
    { "0.9.3",    "000903" },
    { "0.9.2",    "000902" },
    { "0.9.1",    "000901" }
};

static int test() {
    int failures = 0;

    for (size_t i = 0; i < sizeof(EXAMPLES) / sizeof(EXAMPLES[0]); ++i) {
        const examples_t& e = EXAMPLES[i];

        const std::string got = re2c::ver_to_vernum(e.in);
        if (got == e.expected) {
            fprintf(stderr, "PASS: re2c::ver_to_vernum('%s') = '%s'\n", e.in, got.c_str());
        } else {
            ++failures;
            if (got.empty()) {
                fprintf(stderr, "FAIL: re2c::ver_to_vernum('%s') returned error\n", e.in);
            } else {
                fprintf(stderr, "FAIL: re2c::ver_to_vernum('%s') = '%s', expected '%s'\n", e.in,
                        got.c_str(), e.expected);
            }
        }
    }

    return failures;
}

} // namespace re2c_test

int main() {
    return re2c_test::test();
}
